<?php
/**
 * Created by 长毋相忘c.
 * 文件用途描述 :
 * Date: 2018/2/18/018
 * Time: 12:06
 */

namespace app\api\service;


use app\lib\enum\ScopeEnum;
use app\lib\exception\TokenException;
use app\lib\exception\WeChatException;
use think\Exception;
use app\api\model\User;
class UserToken extends Token
{
    protected $code;
    protected $wxAppID;
    protected $wxAppSecret;
    protected $wxLoginUrl;

    public function __construct($code)
    {
        $this->code = $code;
        $this->wxAppID = config('app_id');
        $this->wxAppSecret = config('app_secret');
        $this->wxLoginUrl = sprintf(config('login_url'),
            $this->wxAppID,$this->wxAppSecret,$this->code);
    }


    public function getToken(){
        $result=curl_get($this->wxLoginUrl);
        //加true$result会变成数组否则会变成对象
        $wxResult=json_decode($result,true);
        if(empty($wxResult)){
            throw new Exception('获取session_key及openid时异常，微信内部错误');
        }else{
            $loginFail=array_key_exists('errcode',$wxResult);
            if($loginFail){
                $this->processLoginError();
            }else{
             return   $this->grantToken($wxResult);
            }
        }
    }
         //颁发令牌
    private function grantToken($wxResult){
        //拿到OPENID
        $openid=$wxResult['openid'];
        //数据库里看一下，openid是否已存在
        $user=User::getByOpenid($openid);
        //如果存在则不处理
        if($user){
            $uid=$user->id;
            //如果不存在那么新增一条user数据
        }else{
            $uid = $this->newUser($openid);
        }
        //生成令牌，准备缓存数据
        $cacheValue=$this->prepareCacheValue($wxResult,$uid);
        // ，写入缓存
        $token=$this->saveToCache($cacheValue);
        //把令牌返回到客户端
        return $token;
        //key:令牌
        //value：wxResult,用户唯一标识uid,权限参数scope(作用域：数字越大权限越高)

    }

    //写入缓存
    private function saveToCache($cacheValue){
        $key=self::generateToken();
        //数组转换成字符串
        $value=json_encode($cacheValue);
        $expire_in=config('token_expire_in');
        $request=cache($key,$value,$expire_in);
        if(!$request){
            throw new TokenException([
                'msg'=>'服务器缓存异常',
                'errorCode'=>10005
            ]);
        }
        return $key;
    }

    //准备缓存数据
    private function prepareCacheValue($wxResult,$uid){
        $cacheValue=$wxResult;
        $cacheValue['uid']=$uid;
        //scope用不同的整数来表示不同的权限
        $cacheValue['scope']=ScopeEnum::User;
        return $cacheValue;
    }


    private function newUser($openid){
        $user=User::create(['openid'=>$openid]);
        return $user->id;
    }

    private function processLoginError($wxResult){
        throw new WeChatException(
            [
                'msg' => $wxResult['errmsg'],
                'errorcode' => $wxResult['errcode']
            ]
        );
    }
}